﻿module TetrisState

open Utilities
open Variable
open Coroutines

[<Measure>]
type point

[<Measure>]
type pixel

[<Measure>]
type s

[<Measure>]
type id

[<Measure>]
type ij

type BlockName = 
    | IPiece = 0
    | TPiece = 1
    | OPiece = 2
    | LPiece = 3
    | JPiece = 4
    | ZPiece = 5
    | SPiece = 6

type GameState = 
  {
    CurrentBlock : Variable<Option<Block>>
    NextBlock : Variable<Option<Block>>
    BlockMatrix : Variable<List<int<id>>>
    PlacedBricks : Variable<List<Brick>>
    Score : Variable<int>
    Level : Variable<int>
  }

  member this.GetCurrentBlock () =
        (!this.CurrentBlock).Value

  member this.GetNextBlock () =
        (!this.NextBlock).Value

  member this.GetScore () =
        !this.Score

  member this.GetLevel () =
        !this.Level

  member this.GetX (i:int) =
        (!(!this.CurrentBlock).Value.Bricks.[i].X) |> int

  member this.GetY (i:int) =
        (!(!this.CurrentBlock).Value.Bricks.[i].Y) |> int

  member this.GetNextX (i:int) =
        (!(!this.NextBlock).Value.Bricks.[i].X) |> int

  member this.GetNextY (i:int) =
        (!(!this.NextBlock).Value.Bricks.[i].Y) |> int

  member this.GetName () =
        (!this.CurrentBlock).Value.Name

  member this.GetNextName () =
        (!this.NextBlock).Value.Name

  member this.GetVelY () =
        if (!this.CurrentBlock).IsSome = true then
          !(!this.CurrentBlock).Value.VelY
        else
          10.0f<pixel/s>
  member this.GetBlockMatrixElementNumber () =
        (!this.BlockMatrix).Length

  member this.GetPlacedBrickName (i:int) =
        (!this.PlacedBricks).[i].Name

  member this.GetPlacedBricksLength () =
        (!this.PlacedBricks).Length

  member this.GetPlacedBrickX (i:int) =
        (!(!this.PlacedBricks).[i].X) |> int

  member this.GetPlacedBrickY (i:int) =
        (!(!this.PlacedBricks).[i].Y) |> int
          

and Block = 
  {
    Name : BlockName
    VelY : Variable<float32<pixel/s>>
    Orientation : Variable<int>
    OrientationRange : int
    Bricks : List<Brick>
  }

and Brick = 
  {
    Name : BlockName
    X : Variable<float32<pixel>>
    Y : Variable<float32<pixel>>
    ID : int
    Indexes : Variable<List<int<ij>>>
  }